package utils

import (
	"context"
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"time"

	"github.com/example/video_backend/pkg/logger"
	"go.uber.org/zap"
)

// HTTPClient 是一个封装了HTTP客户端的结构体
type HTTPClient struct {
	client *http.Client
}

// NewHTTPClient 创建一个新的HTTP客户端实例
// proxyURL: 代理服务器地址，如 "http://127.0.0.1:7890"
// 如果不需要代理，可以传入空字符串
func NewHTTPClient(proxyURL string) *HTTPClient {
	client := &http.Client{
		Timeout: 300 * time.Second, // 设置较长的超时时间，因为下载视频可能需要较长时间
	}

	// 这里不直接设置代理，而是让调用方通过环境变量或系统设置来使用Clash代理
	// 在实际使用时，客户端应该设置HTTP_PROXY和HTTPS_PROXY环境变量指向Clash的代理地址

	return &HTTPClient{
		client: client,
	}
}

// DownloadFileWithProxy 通过代理下载文件
// ctx: 上下文，可用于取消操作
// url: 要下载的文件URL
// savePath: 文件保存路径
// return: 下载的文件路径，以及可能的错误
func (c *HTTPClient) DownloadFileWithProxy(ctx context.Context, url string, savePath string) (string, error) {
	logger.Info("开始通过代理下载文件", zap.String("url", url), zap.String("savePath", savePath))

	// 确保保存目录存在
	dir := filepath.Dir(savePath)
	if err := os.MkdirAll(dir, 0755); err != nil {
		return "", fmt.Errorf("无法创建保存目录: %w", err)
	}

	// 创建保存文件
	destFile, err := os.Create(savePath)
	if err != nil {
		return "", fmt.Errorf("无法创建保存文件: %w", err)
	}
	defer destFile.Close()

	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return "", fmt.Errorf("创建请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")

	// 发送请求
	resp, err := c.client.Do(req)
	if err != nil {
		return "", fmt.Errorf("发送请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("服务器返回非成功状态码: %d", resp.StatusCode)
	}

	// 将响应内容写入文件
	size, err := io.Copy(destFile, resp.Body)
	if err != nil {
		return "", fmt.Errorf("写入文件失败: %w", err)
	}

	logger.Info("文件下载完成", zap.String("path", savePath), zap.Int64("size", size))

	return savePath, nil
}

// GetFileWithProxy 通过代理获取文件内容
// ctx: 上下文，可用于取消操作
// url: 要获取的文件URL
// return: 文件内容的字节数组，以及可能的错误
func (c *HTTPClient) GetFileWithProxy(ctx context.Context, url string) ([]byte, error) {
	logger.Info("开始通过代理获取文件内容", zap.String("url", url))

	// 创建请求
	req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %w", err)
	}

	// 设置请求头
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36")

	// 发送请求
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("发送请求失败: %w", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("服务器返回非成功状态码: %d", resp.StatusCode)
	}

	// 读取响应内容
	content, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取文件内容失败: %w", err)
	}

	logger.Info("文件内容获取完成", zap.String("url", url), zap.Int("size", len(content)))

	return content, nil
}